package com.sky.service.impl;

import com.sky.dto.GoodsSalesDTO;
import com.sky.entity.Orders;
import com.sky.mapper.OrderMapper;

import com.sky.mapper.ReportMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.vo.OrderReportVO;
import com.sky.vo.SalesTop10ReportVO;
import com.sky.vo.TurnoverReportVO;
import com.sky.vo.UserReportVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ReportServiceImpl implements ReportService {


    @Autowired
    private ReportMapper reportMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;

    /**
     * 营业额统计
     *
     * @param begin
     * @param end
     * @return 获取需要查询营业额的天数列表
     * 调用mapper查询每天的营业额
     * 处理拼装成VO
     */
    @Override
    public TurnoverReportVO getTurnover(LocalDate begin, LocalDate end) {
        //获取需要查询营业额的天数列表
        List<LocalDate> dateList = new ArrayList<>();
        //2023-05-01 2023-05-03
        dateList.add(begin);
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);
            dateList.add(begin);
        }
        //调用mapper查询每天的营业额
        List<Double> turnoverList = new ArrayList<>();//需要查询的营业额
        for (LocalDate date : dateList) {



            //获取每天的最大时间和最小时间
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            //select sum(amount) from orders where order_time >=#{beginTime}and order_time <=#{endTime} and status =#{status};


            Map<String, Object> map = new HashMap<>();
            map.put("beginTime", beginTime);
            map.put("endTime", endTime);
            map.put("status", Orders.COMPLETED);
            Double turnover = orderMapper.sum(map);

            if (turnover == null) {
                turnover = 0.0;
            }

            turnoverList.add(turnover);
        }

        //处理拼装成VO
        return TurnoverReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .turnoverList(StringUtils.join(turnoverList, ","))
                .build();
    }

    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
        /**
         * 用户统计
         *
         * @param begin
         * @param end
         * @return 获取需要查询新增用户的天数列表
         * 遍历统计截止到当天总用户
         * 遍历统计截止到当天新增用户
         * 封装VO
         */

        List<LocalDate> dateList = new ArrayList<>();
        //2023-05-01 2023-05-03
        dateList.add(begin);
        // 如果最大时间与最小时间不想等 便添加 相等结束
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);
            dateList.add(begin);
        }

        List<Integer> countTotalUserList = new ArrayList<>();
        List<Integer> countNewUserList = new ArrayList<>();
        for (LocalDate date : dateList) {
            //获取每天的最大时间和最小时间
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            //遍历统计截止到当天总用户
            //select count(openid) from user where  create_time <='2023-04-25 23:59:59';
            Map<String, Object> map = new HashMap<>();
            map.put("endTime", endTime);
            Integer countTotalUser = userMapper.sum(map);// 用mapper中的(增删改查) 查map(用户总人数)
            //遍历统计截止到当天新增用户
            //select count(openid) from user where create_time>='2023-04-25 0:0:0'and create_time <='2023-04-25 23:59:59';
            map.put("beginTime", beginTime);
            Integer countNewUser = userMapper.sum(map);
            countTotalUserList.add(countTotalUser);
            countNewUserList.add(countNewUser);
        }
        return UserReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .newUserList(StringUtils.join(countNewUserList, ","))
                .totalUserList(StringUtils.join(countTotalUserList, ","))
                .build();
    }

    /**
     * 订单查询
     *
     * @param begin
     * @param end
     * @return 获取需要查询统计订单的天数列表
     * 查询每日订单数加入 每日订单list
     * 查询每日有效订单数加入每日有效订单list
     * 查询订单总数
     * 查询有效订单数
     * 获取订单完成率
     * 封装Vo
     */
    @Override
    public OrderReportVO getOrderStatistics(LocalDate begin, LocalDate end) {
//        获取需要查询统计订单的天数列表
        List<LocalDate> dateList = new ArrayList<>();
        dateList.add(begin);
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);
            dateList.add(begin);
        }
        List<Integer> countTotalOrderList = new ArrayList<>();
        List<Integer> countValidOrderList = new ArrayList<>();
        //遍历天数列表
        for (LocalDate date : dateList) {
            //获取每天的最大时间和最小时间
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            //   查询每日订单数加入 每日订单list
            //select count(id) from orders where order_time>='2023-04-27 0:0:0'and order_time <='2023-04-27 23:59:59';
            Integer countTotalOrder = countOrderByTimeAndStatus(beginTime, endTime, null);
            //   查询每日有效订单数加入 每日有效订单list
            //select count(id) from orders where order_time>='2023-04-27 0:0:0'and order_time <='2023-04-27 23:59:59' and status =5;
            Integer countValidOrder = countOrderByTimeAndStatus(beginTime, endTime, Orders.COMPLETED);
            countTotalOrderList.add(countTotalOrder);
            countValidOrderList.add(countValidOrder);
        }
        LocalDateTime beginTime = LocalDateTime.of(dateList.get(0), LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
        //查询订单总数
        Integer countTotalOrder = countOrderByTimeAndStatus(beginTime, endTime, null);
        //查询有效订单数
        Integer countValidOrder = countOrderByTimeAndStatus(beginTime, endTime, Orders.COMPLETED);
        //查询订单总数
//        Integer countTotalOrder = countTotalOrderList.stream().reduce(Integer::sum).get();
//        //查询有效订单数
//        Integer countValidOrder = countValidOrderList.stream().reduce(Integer::sum).get();
        //获取订单完成率
        Double orderCompletionRate = 0.0;
        if (countTotalOrder != 0) {
            orderCompletionRate = countValidOrder.doubleValue() / countTotalOrder;// 订单完成率=有效订单数/订单总数
        }
        return OrderReportVO.builder()
                .dateList(StringUtils.join(dateList, ","))
                .orderCompletionRate(orderCompletionRate)
                .orderCountList(StringUtils.join(countTotalOrderList, ","))
                .validOrderCountList(StringUtils.join(countValidOrderList, ","))
                .totalOrderCount(countTotalOrder)
                .validOrderCount(countValidOrder)
                .build();
    }

    /**
     * 查询指定时间区间内的销量排名top10
     * @param begin
     * @param end
     * @return
     * */
    @Override
    public SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end){
        // 获取每天 最大时间最小时间
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
        List<GoodsSalesDTO> goodsSalesDTOList = orderMapper.getSalesTop10(beginTime, endTime);
//  下面这个是stream流
        String nameList = StringUtils.join(goodsSalesDTOList.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList()),",");
        String numberList = StringUtils.join(goodsSalesDTOList.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList()),",");

        return SalesTop10ReportVO.builder()
                .nameList(nameList)
                .numberList(numberList)
                .build();
    }

    private Integer countOrderByTimeAndStatus(LocalDateTime beginTime, LocalDateTime endTime, Integer status) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("beginTime", beginTime);
        map.put("endTime", endTime);
        map.put("status", status);
        return orderMapper.countOrderByTimeAndStatus(map);
    }

}









